using AutoMapper;
using MediatR;
using S.M.SmartMedical.API.Write.Application.Command;
using S.M.SmartMedical.Domain.DTOs;
using S.M.SmartMedical.Domain.Entities;
using S.M.SmartMedical.Domain.Enums;
using S.M.SmartMedical.ErrorCode;
using S.M.SmartMedical.Infrastructure;
using S.M.SmartMedical.Infrastructure.BaseRepository;
using System.Security.Cryptography;
using System.Text;

namespace S.M.SmartMedical.API.Write.Application.Handler
{
    /// <summary>
    /// 用户注册命令处理器
    /// </summary>
    public class RegisterUserHandler : IRequestHandler<RegisterUserCommand, APIResult<UserInfoDto>>
    {
        private readonly IRepository<User> _userRepository;
        private readonly IMapper _mapper;
        private readonly ILogger<RegisterUserHandler> _logger;
        private readonly MyDbContext _context;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="userRepository">用户仓储</param>
        /// <param name="mapper">对象映射器</param>
        /// <param name="logger">日志记录器</param>
        /// <param name="context">数据库上下文</param>
        public RegisterUserHandler(
            IRepository<User> userRepository,
            IMapper mapper,
            ILogger<RegisterUserHandler> logger,
            MyDbContext context)
        {
            _userRepository = userRepository;
            _mapper = mapper;
            _logger = logger;
            _context = context;
        }

        /// <summary>
        /// 处理用户注册命令
        /// </summary>
        /// <param name="request">注册命令</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>注册结果</returns>
        public async Task<APIResult<UserInfoDto>> Handle(RegisterUserCommand request, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("开始处理用户注册，用户名：{UserName}", request.UserRegister.UserName);

                // 检查用户名是否已存在
                var existingUser = await _userRepository.GetAsync(u => u.UserName == request.UserRegister.UserName);
                if (existingUser != null)
                {
                    _logger.LogWarning("用户名已存在：{UserName}", request.UserRegister.UserName);
                    return new APIResult<UserInfoDto>
                    {
                        Code = APIEnum.Fail,
                        Message = "用户名已存在",
                        Data = null!
                    };
                }

                // 检查手机号是否已存在（如果提供了手机号）
                if (!string.IsNullOrEmpty(request.UserRegister.Phone))
                {
                    var existingPhoneUser = await _userRepository.GetAsync(u => u.Phone == request.UserRegister.Phone);
                    if (existingPhoneUser != null)
                    {
                        _logger.LogWarning("手机号已存在：{Phone}", request.UserRegister.Phone);
                        return new APIResult<UserInfoDto>
                        {
                            Code = APIEnum.Fail,
                            Message = "手机号已存在",
                            Data = null!
                        };
                    }
                }

                // 检查邮箱是否已存在（如果提供了邮箱）
                if (!string.IsNullOrEmpty(request.UserRegister.Email))
                {
                    var existingEmailUser = await _userRepository.GetAsync(u => u.Email == request.UserRegister.Email);
                    if (existingEmailUser != null)
                    {
                        _logger.LogWarning("邮箱已存在：{Email}", request.UserRegister.Email);
                        return new APIResult<UserInfoDto>
                        {
                            Code = APIEnum.Fail,
                            Message = "邮箱已存在",
                            Data = null!
                        };
                    }
                }

                // 创建新用户
                var newUser = new User
                {
                    UserName = request.UserRegister.UserName,
                    RealName = request.UserRegister.RealName,
                    Phone = request.UserRegister.Phone,
                    Email = request.UserRegister.Email,
                    Password = HashPassword(request.UserRegister.Password),
                    Status = UserStatus.Normal,
                    CreateTime = DateTime.Now,
                    CreateUserName = request.UserRegister.UserName,
                    IsDeleted = false
                };

                // 保存用户
                var result = await _userRepository.AddAsync(newUser);
                
                // 执行数据库保存操作
                var saveResult = await _context.SaveChangesAsync(cancellationToken);
                
                if (saveResult > 0)
                {
                    _logger.LogInformation("用户注册成功，用户名：{UserName}，用户ID：{UserId}", newUser.UserName, newUser.Id);

                    // 映射返回数据
                    var userInfo = _mapper.Map<UserInfoDto>(newUser);
                    return new APIResult<UserInfoDto>
                    {
                        Code = APIEnum.OK,
                        Message = "注册成功",
                        Data = userInfo
                    };
                }
                else
                {
                    _logger.LogError("用户注册失败，数据库保存失败，用户名：{UserName}", request.UserRegister.UserName);
                    return new APIResult<UserInfoDto>
                    {
                        Code = APIEnum.Fail,
                        Message = "注册失败，请稍后重试",
                        Data = null!
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "用户注册过程中发生异常，用户名：{UserName}", request.UserRegister.UserName);
                return new APIResult<UserInfoDto>
                {
                    Code = APIEnum.Fail,
                    Message = "注册失败，系统异常",
                    Data = null!
                };
            }
        }

        /// <summary>
        /// 密码哈希加密
        /// </summary>
        /// <param name="password">原始密码</param>
        /// <returns>加密后的密码</returns>
        private static string HashPassword(string password)
        {
            using var sha256 = SHA256.Create();
            var hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password));
            return Convert.ToBase64String(hashedBytes);
        }
    }
}